// ------------------------------------------------------------------------------------------------
// File   : DX9AfterEffectManager.cpp
// Date   : 2012-08-01
// Author : Weng xiao yi
// Descr. : Setup the after effects
//          Manage after effects calls, order and parameters routing
//          Put all after effects parameters in context for possible multi-threading
//
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// HEADERS
// ------------------------------------------------------------------------------------------------

#include "DX9AfterEffectManager.h"




// ------------------------------------------------------------------------------------------------
// IMPLEMENTATION 
// ------------------------------------------------------------------------------------------------

DX9AfterEffectManager::DX9AfterEffectManager(void)
{
	// Initialize everything to NULL
	for (int i=0; i < AE_Num_Effects; i++)
	{
		m_apoEffects[i] = NULL;
	}
	m_pDevice = NULL;
}

DX9AfterEffectManager::~DX9AfterEffectManager(void)
{
}

void DX9AfterEffectManager::Initialize(LPDIRECT3DDEVICE9 pDevice)
{
	m_pDevice = pDevice;
	// create all effect instances
	//m_apoEffects[AE_Bloom] = new DX9AE_Bloom();
	//m_apoEffects[AE_PostFog] = new DX9AE_PostFog();
	//m_apoEffects[AE_DOF] = new DX9AE_DOF();
	//m_apoEffects[AE_FXAA] = new DX9AE_FXAA();
	//m_apoEffects[AE_HeadLight] = new DX9AE_HeadLight();
	//m_apoEffects[AE_Gamma] = new DX9AE_Gamma();
}

void DX9AfterEffectManager::Shutdown(void)
{
	// delete all effect instances
	for(int i =0; i < AE_Num_Effects; i++)
	{
		if(m_apoEffects[i])
			delete m_apoEffects[i];
		m_apoEffects[i] = NULL;
	}
}

void DX9AfterEffectManager::OnDeviceLost(void)
{
	// Set device lost for all effects

	for(int i=0; i<AE_Num_Effects; i++)
	{
		if(m_apoEffects[i])
		{
			m_apoEffects[i]->OnDeviceLost();
		}
	}
}

void DX9AfterEffectManager::OnDeviceReset(void)
{
	//if( m_apoEffects[AE_Bloom] == NULL )
	//	m_apoEffects[AE_Bloom] = new DX9AE_Bloom();
	//if( m_apoEffects[AE_PostFog] == NULL )
	//	m_apoEffects[AE_PostFog] = new DX9AE_PostFog();
	//if( m_apoEffects[AE_DOF] == NULL )
	//	m_apoEffects[AE_DOF] = new DX9AE_DOF();
	//if( m_apoEffects[AE_FXAA] == NULL)
	//	m_apoEffects[AE_FXAA] = new DX9AE_FXAA();
	//if( m_apoEffects[AE_HeadLight] == NULL )
	//	m_apoEffects[AE_HeadLight] = new DX9AE_HeadLight();
	//if( m_apoEffects[AE_Gamma] == NULL )
	//	m_apoEffects[AE_Gamma] = new DX9AE_Gamma();

	// set device reset for all effects
	for(int i=0; i<AE_Num_Effects; i++)
	{
		if(m_apoEffects[i])
		{
			m_apoEffects[i]->OnDeviceReset();
		}
	}
}

void DX9AfterEffectManager::BeginRender(void)
{
	LPDIRECT3DVERTEXDECLARATION9 pAfterEffectDeclVD = NULL;
	LPDIRECT3DVERTEXBUFFER9		 pQuadVB = NULL;

	for(int i=0; i<AE_Num_Effects; i++)
	{
		if( m_apoEffects[i] && (pAfterEffectDeclVD == NULL) && (pQuadVB == NULL) )
		{
			if( m_apoEffects[i]->IsEnabled(eDX9_AE_Context_Read) )
			{
				pAfterEffectDeclVD = m_apoEffects[AE_HeadLight]->GetVertexDecl();
				pQuadVB = m_apoEffects[AE_HeadLight]->GetVertexBuffer();
			}
		}
	}

	if( pAfterEffectDeclVD && pQuadVB )
	{
		m_pDevice->SetVertexDeclaration( pAfterEffectDeclVD );
		m_pDevice->SetStreamSource( 0, pQuadVB, 0, sizeof(AfterEffectQuadVertex) );
	}
}

void DX9AfterEffectManager::ApplyEffects(void)
{
	//---------------------------------------------------------------------------------------------
	// APPLY EFFECTS
	// Call Order is IMPORTANT!!!

	BeginRender();

	// HeadLight
	if( m_apoEffects[AE_HeadLight]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_HeadLight]->Apply();

	// FXAA
	if( m_apoEffects[AE_FXAA]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_FXAA]->Apply();

	// Post process Fog Effect
	if( m_apoEffects[AE_PostFog]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_PostFog]->Apply();

	// Depth Of Field (DOF)
	if( m_apoEffects[AE_DOF]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_DOF]->Apply();

	// Bloom Effect
	if( m_apoEffects[AE_Bloom]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_Bloom]->Apply();

	// GammaCorrection
	if( m_apoEffects[AE_Gamma]->IsEnabled(eDX9_AE_Context_Read) )
		m_apoEffects[AE_Gamma]->Apply();
}

